﻿/* UTF-8 */

/*
 * draw a run of text in scene
 * Copyright 2016 tianxianglong. All rights reserved.
 */

/*
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "drawtext.h"
#include <Windows.h>
#include "glyph.h"
#include "render_window.h"
#include "glyphtexture.h"

FONTINSTANCE FontInstance;

static SHORT DoDrawChar(SHORT pen_x, SHORT baseline, GLYPHCOORD *coord, UINT tid)
{
	float cx = (float)(coord->x2 - coord->x);
	float cy = (float)(coord->y2 - coord->y);

	float left = (float)(pen_x - coord->ox);
	float top = (float)(baseline - coord->oy);
	float right = (float)(left + cx);
	float bottom = (float)(top + cy);

	float tex_left = coord->u;
	float tex_top = coord->v;
	float tex_right = coord->u2;
	float tex_bottom = coord->v2;

	DWORD color = D3DCOLOR_ARGB(255, 0, 0, 0);

	struct SCREEN_COLOR_VERTEX pt[6] = {
		/* 第一个三角形 */
		{ left, top, 0.0f, 1.0f, color, tex_left, tex_top },
		{ right, top, 0.0f, 1.0f, color, tex_right, tex_top },
		{ left, bottom, 0.0f, 1.0f, color, tex_left, tex_bottom },

		/* 第二个三角形 */
		{ left, bottom, 0.0f, 1.0f, color, tex_left, tex_bottom },
		{ right, top, 0.0f, 1.0f, color, tex_right, tex_top },
		{ right, bottom, 0.0f, 1.0f, color, tex_right, tex_bottom },
	};

	DrawScreenColorRect(pt, 6, tid);

	return coord->ax;
}

static int FindKerning(WCHAR p, WCHAR c)
{
	LPKERNINGPAIR kerning = FontInstance.glyphtex->Font->kerning;

	for (DWORD i = 0; i < FontInstance.glyphtex->Font->kern_count; ++i)
	{
		if (kerning[i].wFirst == p
			&& kerning[i].wSecond == c)
		{
			return kerning[i].iKernAmount;
		}
	}

	return 0;
}

void DrawString(SHORT x, SHORT y, LPCWSTR Str)
{
	size_t cch = wcslen(Str);

	SHORT pen_x = x;
	SHORT baseline = y;
	SHORT kern = 0;

	for (size_t i = 0; i < cch; ++i)
	{
		USHORT tex = FontInstance.indices->texture[Str[i]];
		USHORT idx = FontInstance.indices->indices[Str[i]];

		if (tex == INVALID_INDEX || idx == INVALID_INDEX)
			continue;

		if (i > 0)
		{
			kern = (SHORT)FindKerning(Str[i - 1], Str[i]);
		}


		GLYPHTEXTUREPTR Texture = FontInstance.glyphtex->Textures[tex];
		GLYPHCOORD coord = Texture->Coords[idx];

		pen_x += DoDrawChar(pen_x, baseline, &coord, Texture->tid);
		pen_x += kern;
	}
}

